﻿// <copyright file="Pulse.cs" company="Microsoft Corporation">
// Copyright (c) 2009 Microsoft Corporation All Rights Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2009-12-30</date>
// <summary>Pulse behavior defintion</summary>

namespace Microsoft.WebAnalytics.Behaviors
{
    using System;
    using System.ComponentModel.Composition;
    using System.Windows;
    using System.Windows.Interactivity;
    using System.Windows.Threading;

    /// <summary>
    /// <img src="../media/Microsoft.WebAnalytics.Behaviors.Pulse.24x24.png"/> 
    /// A Pulse event that sends a "Timer" analytics event at a prescribed interval
    /// </summary>
    /// <remarks>
    /// These are the properties in the AnalyticsEvent that are set by the Pulse behavior at each interval
    /// <list type="table">
    /// <listheader>
    ///     <term>AnalyticsEvent Property</term>
    ///     <description>Description</description>
    /// </listheader>
    /// <item>
    /// <term>Name</term><description>Timer</description>
    /// </item>
    /// <item>
    /// <term>ObjectName</term>
    /// <description>AssociatedObject.Name</description>
    /// </item>
    /// <item>
    /// <term>TimeCode</term>
    /// <description>timespan since the associated object was loaded</description>
    /// </item>
    /// <item>
    /// <term>Value</term>
    /// <description>number of seconds since the associated object was loaded</description>
    /// </item>
    /// </list>
    /// </remarks>
    public class Pulse : Behavior<FrameworkElement>
    {
        #region Fields
        /// <summary>
        /// the Dispatcher Timer
        /// </summary>
        private DispatcherTimer timer;

        /// <summary>
        /// The application start time
        /// </summary>
        private DateTime startTime;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the Pulse class
        /// </summary>
        public Pulse()
        {
            this.Interval = 30;
        }

        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the interval in seconds
        /// </summary>
        /// <remarks>Default is 30 seconds</remarks>
        public int Interval { get; set; }

        /// <summary>
        /// Gets or sets the event Logging method
        /// </summary>
        [Import("Log")]
        public Action<AnalyticsEvent> Log { get; set; }
        #endregion

        #region Methods
        /// <summary>
        /// Attach the timer
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            CompositionInitializerEx.SatisfyImports(this);

            this.StartTimer();

            this.AssociatedObject.Unloaded += new RoutedEventHandler(delegate(object sender, RoutedEventArgs args)
            {
                System.Windows.Interactivity.Interaction.GetBehaviors(this.AssociatedObject).Remove(this);
            });
        }

        /// <summary>
        /// detach the timer
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            if (this.timer != null)
            {
                if (this.timer.IsEnabled)
                {
                    this.timer.Stop();
                }

                this.timer.Tick -= new EventHandler(this.OnTick);
            }
        }
        #endregion

        #region Implementation

        /// <summary>
        /// Start the timer
        /// </summary>
        private void StartTimer()
        {
            if (this.Interval > 0)
            {
                this.timer = new DispatcherTimer();

                this.timer.Interval = new TimeSpan(0, 0, this.Interval);

                this.timer.Tick += new EventHandler(this.OnTick);

                this.startTime = DateTime.Now;

                this.timer.Start();
            }
        }

        /// <summary>
        /// Log a Timer event
        /// </summary>
        /// <param name="sender">the dispatch timer</param>
        /// <param name="e">the event arguments</param>
        private void OnTick(object sender, EventArgs e)
        {
            var now = DateTime.Now;

            var timeSpan = now - this.startTime;

            var seconds = System.Convert.ToInt32(Math.Floor(timeSpan.TotalSeconds + 0.5));

            var logEvent = new AnalyticsEvent()
            {
                Name = "Timer",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().ToString(),
                Value = seconds
            };

            this.Log(logEvent);
        }
        #endregion
    }
}